﻿using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Casamiel.Application;
using Casamiel.Common;

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using NLog;

namespace Casamiel.API.Infrastructure.Filters
{
    /// <summary>
    /// 快乐土地token验证
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate)]
    public class CheckHLTokenAttribute : Attribute, IAsyncActionFilter
    {
        private readonly IMemberService _member;
        private readonly NLog.ILogger logger = LogManager.GetLogger("OpenInfo");



        /// <summary>
        /// 
        /// </summary>
        /// <param name="memberService"></param>
        public CheckHLTokenAttribute(IMemberService memberService)
        {
           _member = memberService;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (next == null)
            {
                throw new ArgumentNullException(nameof(next));
            }

            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("cssupersecret_secretke!miel"));
            var tokenValidationParameters = new TokenValidationParameters
            {
                // The signing key must match!
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,

                // Validate the JWT Issuer (iss) claim
                ValidateIssuer = true,
                ValidIssuer = "CasamielIssuer",

                // Validate the JWT Audience (aud) claim
                ValidateAudience = true,
                ValidAudience = "casamiel",

                // Validate the token expiry
                ValidateLifetime = true,

                // If you want to allow a certain amount of clock drift, set that here:
                ClockSkew = TimeSpan.Zero
            };
            var token = context.HttpContext.Request.Headers["u-token"];
            //var userAgent = string.IsNullOrEmpty(context.HttpContext.Request.Headers["User-Agent"].ToString()) ? context.HttpContext.Request.Headers["UserAgent"].ToString() : context.HttpContext.Request.Headers["User-Agent"].ToString();
            int loginType = 5;
            //if (userAgent.ToUpper(CultureInfo.InvariantCulture).Contains("CASAMIEL", StringComparison.CurrentCulture))
            //{
            //	loginType = 1;
            //}
            //if (userAgent.ToUpper(CultureInfo.InvariantCulture).Contains("DONCO", StringComparison.CurrentCulture))
            //{
            //	loginType = 1;
            //}
            //if (userAgent.Contains("MicroMessenger", StringComparison.CurrentCulture))
            //{
            //	loginType = 3;//微信端
            //}
            if (string.IsNullOrEmpty(token))
            {
                context.Result = new JsonResult(new { code = -18, msg = "token无效" });
                return;
            }

            var handler = new JwtSecurityTokenHandler();
            ClaimsPrincipal principal = null;
            SecurityToken validToken = null;
            try
            {
                principal = handler.ValidateToken(token, tokenValidationParameters, out validToken);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                logger.Error($"]CheckToken]token:[{token}] token无效");
                context.Result = new JsonResult(new { code = -18, msg = "token无效" });
                return;
            }
            var validJwt = validToken as JwtSecurityToken;

            if (validJwt == null)
            {
                logger.Error($"CheckToken,token:[{token}] token无效");
                context.Result = new JsonResult(new { code = -18, msg = "token无效" });
                return;
            }
            JwtSecurityToken dtoken = handler.ReadJwtToken(token);
            var rsa = new RSAHelper(RSAType.RSA2, Encoding.UTF8, RSAHelper.privateKey, RSAHelper.publicKey);

            var exp = dtoken.Payload.Exp;
            string mobile = rsa.Decrypt(dtoken.Payload.Jti);
            //  Console.WriteLine(new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds());
            if (exp < new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds())
            {
                logger.Error($"CheckToken,token:[{token}] 登录凭证已过期，请重新登陆");
                context.Result = new JsonResult(new { code = -14, msg = "登录凭证已过期，请重新登陆" });
                return;
            }
            else
            {
                var mtoken = await _member.FindAsync<ICasaMielSession>(mobile, loginType).ConfigureAwait(false);
                if (mtoken == null || !mtoken.Access_Token.Equals(token, StringComparison.CurrentCultureIgnoreCase))
                {
                    logger.Error($"CheckToken,token:[{token}] 登录凭证已过期，请重新登陆");
                    context.Result = new JsonResult(new { code = -18, msg = "登录凭证已过期，请重新登陆" });
                    return;
                }

            }
            await next().ConfigureAwait(false);
        }
    }
}
